package com.spbdx.common.utils;

import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
import org.springframework.util.ClassUtils;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.HashSet;
import java.util.Set;

/**
 * Description 环境扫描工具
 *
 * @author chenwei
 * @version 1.0
 * @date 2023/3/13 16:46
 */
public class PackageUtil {
    private static final PathMatchingResourcePatternResolver RESOLVER = new PathMatchingResourcePatternResolver();
    private static final SimpleMetadataReaderFactory REGISTER = new SimpleMetadataReaderFactory();
    private static final StandardEnvironment ENVIRONMENT = new StandardEnvironment();

    private PackageUtil() {
    }

    private static String toBaseResourcePath(String basePackage) {
        if (StringUtils.isEmpty(basePackage)) {
            return "";
        } else {
            String resourcePath = "classpath*:" + ClassUtils.convertClassNameToResourcePath(ENVIRONMENT.resolveRequiredPlaceholders(basePackage)) + '/' + "**/*.class";
            return resourcePath;
        }
    }

    public static Set<Class> scanClasses(String basePackage, Class<? extends Annotation> annotation) {
        String packagePath = toBaseResourcePath(basePackage);
        HashSet classes = new HashSet(512);

        Resource[] resources;
        try {
            resources = RESOLVER.getResources(packagePath);
        } catch (IOException var15) {
            return classes;
        }

        Resource[] var5 = resources;
        int var6 = resources.length;

        for (int var7 = 0; var7 < var6; ++var7) {
            Resource resource = var5[var7];

            MetadataReader metadataReader;
            try {
                metadataReader = REGISTER.getMetadataReader(resource);
            } catch (IOException var17) {
                continue;
            }

            AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
            if (annotationMetadata.hasAnnotation(annotation.getName())) {
                ClassMetadata classMetadata = metadataReader.getClassMetadata();
                String className = classMetadata.getClassName();

                Class clazz;
                try {
                    clazz = Class.forName(className);
                } catch (ClassNotFoundException var16) {
                    continue;
                }

                classes.add(clazz);
            }
        }

        return classes;
    }
}
